Now that Owen explained the algorithm, I think I implemented it right for
authorDarin Adler <darin@src.gnome.org>
Fri, 5 May 2000 02:50:24 +0000 (02:50 +0000)
committerDarin Adler <darin@src.gnome.org>
Fri, 5 May 2000 02:50:24 +0000 (02:50 +0000)
* gdk-pixbuf/pixops/pixops.c: (pixops_composite_nearest),
(composite_pixel), (composite_line):
* gdk-pixbuf/test-gdk-pixbuf.c: (simple_composite_test_one_type):
Now that Owen explained the algorithm, I think I implemented it
right for the cases where the destination pixbuf is not opaque.
The test does seem to confirm it.

gdk-pixbuf/ChangeLog
gdk-pixbuf/pixops/pixops.c
gdk-pixbuf/test-gdk-pixbuf.c

index d41d8e664f1788e1f9c4220a08f0972081ee5505..5f7ef0843718e2e511a20856332cf4e0d3ed1ab8 100644 (file)
@@ -1,3 +1,12 @@
+2000-05-04  Darin Adler  <darin@eazel.com>
+
+       * gdk-pixbuf/pixops/pixops.c: (pixops_composite_nearest),
+       (composite_pixel), (composite_line):
+       * gdk-pixbuf/test-gdk-pixbuf.c: (simple_composite_test_one_type):
+       Now that Owen explained the algorithm, I think I implemented it
+       right for the cases where the destination pixbuf is not opaque.
+       The test does seem to confirm it.
+
 2000-05-04  Darin Adler  <darin@eazel.com>
 
        * gdk-pixbuf/.cvsignore:
index 00652d5c67f09bb3d822a6174e2e474c95abb8c4..ae0ff5ee7c400496532c5a44b6a70fd0b4afb72c 100644 (file)
@@ -177,10 +177,24 @@ pixops_composite_nearest (guchar        *dest_buf,
 
          if (dest_has_alpha)
            {
-             dest[0] = (a0 * src[0] + (0xff - a0) * dest[0]) / 0xff;
-             dest[1] = (a0 * src[1] + (0xff - a0) * dest[1]) / 0xff;
-             dest[2] = (a0 * src[2] + (0xff - a0) * dest[2]) / 0xff;
-             dest[3] = (0xff * a0 + (0xff - a0) * dest[3]) / 0xff;
+             unsigned int w0 = 0xff * a0;
+             unsigned int w1 = (0xff - a0) * dest[3];
+             unsigned int w = w0 + w1;
+
+             if (w != 0)
+               {
+                 dest[0] = (w0 * src[0] + w1 * dest[0]) / w;
+                 dest[1] = (w0 * src[1] + w1 * dest[1]) / w;
+                 dest[2] = (w0 * src[2] + w1 * dest[2]) / w;
+                 dest[3] = w / 0xff;
+               }
+             else
+               {
+                 dest[0] = 0;
+                 dest[1] = 0;
+                 dest[2] = 0;
+                 dest[3] = 0;
+               }
            }
          else
            {
@@ -296,12 +310,24 @@ composite_pixel (guchar *dest, int dest_x, int dest_channels, int dest_has_alpha
 {
   if (dest_has_alpha)
     {
-      unsigned int w = (0xff0000 - a) * dest[3];
+      unsigned int w0 = a - (a >> 8);
+      unsigned int w1 = ((0xff0000 - a) >> 8) * dest[3];
+      unsigned int w = w0 + w1;
       
-      dest[0] = (r + (0xff0000 - a) * dest[0]) / 0xff0000;
-      dest[1] = (g + (0xff0000 - a) * dest[1]) / 0xff0000;
-      dest[2] = (b + (0xff0000 - a) * dest[2]) / 0xff0000;
-      dest[3] = (0xff * a + (0xff0000 - a) * dest[3]) / 0xff0000;
+      if (w != 0)
+       {
+         dest[0] = (r - (r >> 8) + w1 * dest[0]) / w;
+         dest[1] = (g - (g >> 8) + w1 * dest[1]) / w;
+         dest[2] = (b - (b >> 8) + w1 * dest[2]) / w;
+         dest[3] = w / 0xff00;
+       }
+      else
+       {
+         dest[0] = 0;
+         dest[1] = 0;
+         dest[2] = 0;
+         dest[3] = 0;
+       }
     }
   else
     {
@@ -354,12 +380,24 @@ composite_line (int *weights, int n_x, int n_y,
 
       if (dest_has_alpha)
        {
-         unsigned int w = (0xff0000 - a) * dest[3];
+         unsigned int w0 = a - (a >> 8);
+         unsigned int w1 = ((0xff0000 - a) >> 8) * dest[3];
+         unsigned int w = w0 + w1;
 
-         dest[0] = (r + (0xff0000 - a) * dest[0]) / 0xff0000;
-         dest[1] = (g + (0xff0000 - a) * dest[1]) / 0xff0000;
-         dest[2] = (b + (0xff0000 - a) * dest[2]) / 0xff0000;
-         dest[3] = (0xff * a + (0xff0000 - a) * dest[3]) / 0xff0000;
+         if (w != 0)
+           {
+             dest[0] = (r - (r >> 8) + w1 * dest[0]) / w;
+             dest[1] = (g - (g >> 8) + w1 * dest[1]) / w;
+             dest[2] = (b - (b >> 8) + w1 * dest[2]) / w;
+             dest[3] = w / 0xff00;
+           }
+         else
+           {
+             dest[0] = 0;
+             dest[1] = 0;
+             dest[2] = 0;
+             dest[3] = 0;
+           }
        }
       else
        {
index b75f2e65e181ba4fb3197138c29d645912daf9c9..c4e22d1c4b63ad266677860103c8f8ed43bdd0e1 100644 (file)
@@ -201,7 +201,8 @@ simple_composite_test_one_type (GdkInterpType type)
        success &= simple_composite_test_one (type, 0x00000000, TRUE, 0xFF0000FF, TRUE, 0xFF0000FF);
        success &= simple_composite_test_one (type, 0x00000000, TRUE, 0x00FF00FF, TRUE, 0x00FF00FF);
        success &= simple_composite_test_one (type, 0x00000000, TRUE, 0x0000FFFF, TRUE, 0x0000FFFF);
-       success &= simple_composite_test_one (type, 0x00FF0080, TRUE, 0xFFFFFF00, TRUE, 0x7FFF7F80);
+       success &= simple_composite_test_one (type, 0x00FF0080, TRUE, 0xFFFFFF00, TRUE, 0x00FF0080);
+       success &= simple_composite_test_one (type, 0xFF000080, TRUE, 0x00FF0040, TRUE, 0xCC32009F);
        success &= simple_composite_test_one (type, 0xFFFFFFFF, TRUE, 0xFFFFFFFF, TRUE, 0xFFFFFFFF);
 
        return success;